package com.jclazz.jweb.codegen.project.ruoyi;

import com.jclazz.jweb.codegen.common.Constants;
import com.jclazz.jweb.codegen.common.ZipGenerator;
import com.jclazz.jweb.codegen.domain.GenerateSchema;
import com.jclazz.jweb.codegen.domain.GenDetails;
import com.jclazz.jweb.codegen.domain.TableMeta;
import com.jclazz.jweb.codegen.exceptions.CodeGeneratorException;
import com.jclazz.jweb.codegen.util.GenUtils;
import com.jclazz.jweb.codegen.util.StringUtils;
import com.jclazz.jweb.codegen.util.VelocityInitializer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
public class RuoYiCodeZipGenerator implements ZipGenerator {

    private final GenerateSchema config;
    private final TableMeta tableMeta;

    public RuoYiCodeZipGenerator(GenerateSchema config, TableMeta tableMeta) {
        this.config = config;
        this.tableMeta = tableMeta;
    }

    @Override
    public void generatorCode(ZipOutputStream zip) {

        GenDetails genDetails = GenUtils.prepare(config, tableMeta);
        VelocityInitializer.initVelocity();
        VelocityContext velocityContext = createVelocityContext(genDetails);
        for (String template : getTemplates()) {
            final String fileName = makeMavenProjectFile(template, genDetails);
            log.info("生成文件：{}", fileName);
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(velocityContext, sw);
            try {
                // 添加到zip
                zip.putNextEntry(new ZipEntry(fileName));
                IOUtils.write(sw.toString(), zip, Constants.UTF8);
                IOUtils.closeQuietly(sw);
                zip.closeEntry();
            } catch (IOException e) {
                throw new CodeGeneratorException("渲染模板失败，表名：" + tableMeta.getTableName() + "，原因：" + e.getMessage());
            }
        }
    }

    protected VelocityContext createVelocityContext(GenDetails genDetails) {
        // 参数传递到模板文件vm
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("author", genDetails.getAuthor());
        velocityContext.put("date", genDetails.getDate());
        velocityContext.put("moduleName", genDetails.getModuleName());
        velocityContext.put("boName", genDetails.getBoName());
        velocityContext.put("domainType", genDetails.getDomainType());
        velocityContext.put("tableMeta", genDetails.getTableMeta());
        velocityContext.put("menuEntry", genDetails.getMenuEntry());
        velocityContext.put("serviceId", genDetails.getServiceId());

        return velocityContext;
    }

    /**
     * 模版文件转换为Maven项目的文件路径，该路径就是可以直接在maven项目中使用文件路径
     */
    public static String makeMavenProjectFile(String template, GenDetails genDetails) {
        // 类型名称
        final String typeName = genDetails.getDomainType().getClassName();
        // 业务对象名称
        final String boName = genDetails.getBoName();

        String javaPath = GenUtils.Helper.javaSrcPathFromPackageName(genDetails.getDomainType().getModulePackageName()) + "/";
        String mybatisPath = GenUtils.Helper.myBaitsResourcePathFromModuleName(genDetails.getModuleName()) + "/" + typeName;
        String htmlPath = GenUtils.Helper.webViewResourcePathFromModuleName(genDetails.getModuleName()) + "/" + boName;

        if (template.contains("domain.java.vm")) {
            return javaPath + "domain" + "/" + typeName + ".java";
        }
        if (template.contains("Mapper.java.vm")) {
            return javaPath + "mapper" + "/" + typeName + "Mapper.java";
        }
        if (template.contains("Service.java.vm")) {
            return javaPath + "service" + "/" + "I" + typeName + "Service.java";
        }
        if (template.contains("ServiceImpl.java.vm")) {
            return javaPath + "service" + "/" + typeName + "ServiceImpl.java";
        }
        if (template.contains("Controller.java.vm")) {
            return javaPath + "controller" + "/" + typeName + "Controller.java";
        }
        if (template.contains("Mapper.xml.vm")) {
            return mybatisPath + "Mapper.xml";
        }
        if (template.contains("list.html.vm")) {
            return htmlPath + "/" + boName + ".html";
        }
        if (template.contains("add.html.vm")) {
            return htmlPath + "/" + "add.html";
        }
        if (template.contains("edit.html.vm")) {
            return htmlPath + "/" + "edit.html";
        }
        if (template.contains("sql.vm")) {
            return boName + "Menu.sql";
        }
        return null;
    }


    /**
     * 获取模板信息
     *
     * @return 模板列表
     */
    protected static List<String> getTemplates() {
        final String basePath = "templates/vm/project/ruoyi/" ;
        List<String> templates = new ArrayList<String>();
        templates.add(basePath + "java/domain.java.vm");
        templates.add(basePath + "java/Mapper.java.vm");
        templates.add(basePath + "java/Service.java.vm");
        templates.add(basePath + "java/ServiceImpl.java.vm");
        templates.add(basePath + "java/Controller.java.vm");
        templates.add(basePath + "xml/Mapper.xml.vm");
        templates.add(basePath + "html/list.html.vm");
        templates.add(basePath + "html/add.html.vm");
        templates.add(basePath + "html/edit.html.vm");
        templates.add(basePath + "sql/sql.vm");
        return templates;
    }
}
